package client;

import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Random;

import repository.Repository;

public class Conductor implements Runnable {

	private ArrayList<Monitor> monitors;
	private Repository musicRepo;
	private int currentBar;
	private int songLength;
	private int initialised;
	private int startAt;
	private int tempo; // in beats per minute (bpm)
	private Random tempoRandomiser;

	private static int BEATSPERBAR = 4;

	/*
	 * Conductor should be started at the relevant bar The first Player to
	 * detect the failure of the Conductor should give its current bar value for
	 * the new Conductor to start at
	 */
	public Conductor(ArrayList<Monitor> mons, Repository repo, int at) {
		monitors = mons;
		currentBar = -1;
		musicRepo = repo;
		initialised = 0;
		startAt = at;
		tempo = 120;
		tempoRandomiser = new Random(System.currentTimeMillis());
	}

	public void run() {
		// Wait a bit till Players have their music

		// Query for a song length
		try {
			Thread.sleep(5000);

			songLength = musicRepo.getSongLength();
			System.out.println(songLength);
		} catch (RemoteException e) {
			System.err.println(e.getMessage());
		}
		// Randomly choose tempo changes
		catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// Start synchronisation
		// Update Players' Monitors on bar beginnings
		while (currentBar < songLength) {
			long startTime = System.currentTimeMillis();
			for (Monitor m : monitors) { // Can this be replaced with a
											// multicast call to multiple
											// Monitors?
				try {
					System.out.println("" + currentBar);
					m.updateTime(currentBar);
				} catch (RemoteException e) {
					System.err.println(e.getMessage());
				} catch (NullPointerException e) {
					System.err.println("Player not available!");
				}
			}
			long busyTime = System.currentTimeMillis() - startTime;
			if (initialised > 4)
				currentBar++;
			else if (initialised < 4)
				initialised++;
			else {
				currentBar = startAt;
				initialised++;
			}
			try {
				if (currentBar % 8 == 0) {
					do {
						boolean inc = tempoRandomiser.nextBoolean();
						if (inc)
							tempo += tempoRandomiser.nextInt(60);
						else
							tempo -= tempoRandomiser.nextInt(60);
						System.out.println("New tempo is: " + tempo);
					} while (tempo < 60 || tempo > 240);
				}
				System.out.println(tempo);
				double sleepTime = (((60.0 / tempo) * 1000) * BEATSPERBAR)
						- (int) busyTime;
				if (!(sleepTime < 0))
					Thread.sleep((int)sleepTime);
			} catch (InterruptedException e) {
				System.err.println(e.getMessage());
			}
		}

		System.out.println("Song's over!");
		System.out.println("Would you like an encore?");

	}
}
